package com.bdqn.common.cofing;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.bdqn.sys.realm.UserRealm;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * shiro的配置类
 */
@Configuration
public class ShiroConfiguration {

    private static final String SHIRO_DIALECT = "shiroDialect";
    private static final String SHIRO_FILTER = "shiroFilter";
    private  String hashAlgorithmName="md5";//加密算法

    private  Integer hashIterations=2;//散列次数

    /**
     * 凭证匹配器HashedCredentialsMatcher是儿子，CredentialsMatcher接口，可以点进去看源码
     * @return
     */
    @Bean("credentialsMatcher")
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher credentialsMatcher=new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName(hashAlgorithmName);//设置加密方式
        credentialsMatcher.setHashIterations(hashIterations);//散列次数
        return credentialsMatcher;
    }


    /**
     * 注入UserRealm
     * @param credentialsMatcher 凭证器注入 之前整合spring就在shiro.xml配置中配置，现在我们要整合springboot就用方法注入
     *  之前xml注入凭证其匹配器时候ref是引用上面的声明凭证匹配器id名字，所以我们这里方法也参数也就是要
     *  用上面@Bean("credentialsMatcher")CredentialsMatcher方法作为参数
     * @return
     */
    @Bean
    public UserRealm getUserRealm(CredentialsMatcher credentialsMatcher){
        UserRealm realm=new UserRealm();
        //注入凭证器
        realm.setCredentialsMatcher(credentialsMatcher);
        return  realm;
    }

    /**
     * 配置SecurityManager 安全管理器
     * @param userRealm
     * @return
     */
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(UserRealm userRealm){
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
        //引用UserRealm
        securityManager.setRealm(userRealm);
        //返回DefaultWebSecurityManager对象
        return  securityManager;

    }

    /**
     *注入拦截器链
     * @param defaultWebSecurityManager 和上面同理也参数也是要引用DefaultWebSecurityManager
     * @return
     */
    @Bean(SHIRO_FILTER)
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
        //创建过滤链对象
        ShiroFilterFactoryBean factoryBean=new ShiroFilterFactoryBean();
        //注入安全管理器
        factoryBean.setSecurityManager(defaultWebSecurityManager);
        //注入未登录的跳转页面，默认是webapp/login.jsp 还有thymeleaf不支持jsp
        factoryBean.setLoginUrl("/login");
        //注入权限不足时跳转的页面
        factoryBean.setUnauthorizedUrl("/unauthorized");
        //设置过滤器链
        Map<String,String> map=new LinkedHashMap<String, String>();
        //设置匿名访问
        map.put("/resources/**","anon");
        map.put("/","anon");
        map.put("/login.html","anon");
        map.put("/login","anon");//放行去到登录页面
        map.put("/sys/user/login","anon");//登录请求
        map.put("/logout","logout");//退出

        //其他请求一律拦截
        map.put("/**","authc");

        //将过滤器链集合设置到ShiroFilterFactoryBean对象中
        factoryBean.setFilterChainDefinitionMap(map);
        //返回对象
        return factoryBean;

    }


    /* 加入注解的使用，不加入这个注解不生效--开始 */
    /**
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
    /* 加入注解的使用，不加入这个注解不生效--结束 */

    /**
     * 为了能在html页面引用shiro标签，上面两个函数必须添加，不然会报错
     * @return
     */
    @Bean(name = SHIRO_DIALECT)
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }

}
